//
//  main.m
//  Study OC
//
//  Created by admin on 2019/7/28.
//  Copyright © 2019 猫爷爷的酱醋茶. All rights reserved.
//

/*
 OC是个弱语言
 编译器在编译的时候，语法检查没那么严格。
 优点：灵活 缺点：灵活
 
 相对于C语言新增的数据类型
    BOOL
    Boolean
    Class
    nil
    SEL
    id:
        万能指针 只能调用对象方法，但是不能使用->访问属性，也不能使用点语法。
        因为其实typedef类型，在自定义的时候已经加* 所以在使用的时候不用加*
 
        与NSObject都是万能指针，不同的是NSObject指向对象成员的方法的时候会进行编译检查，
        而id不会，直接通过。
 
 

 
 面向对象的三大特征
 
    1. 封装
        函数是封装的一个体现，
        类是更高级的封装，类将数据和方法封装为一个整体。
       优点：
        a）屏蔽内部的实现，外界无需知道具体的内部实现，只需要懂得调用即可；
        b）方便操作，方便后期的维护
 
    2. 继承
 
    3. 多态
 
 NS前缀
 
    OC 里面有很多NS开头的数据类型，比如NSString、NSLog...
    是因为，原本开发的界面工具名为NextStep，其后更名为cocoa，为了区分，所以用NS做前缀。
    大部分都在Foundation框架内。
 
 @ 符号
 
    1.将C字符串转换为OC字符串
    2.OC中的绝大部分关键词都是以@开头 @aotoreleasepool、@public...
 
 
 OC程序的编译、链接、执行
 
    1）在.m文件中写上符合OC语法规范的源代码
    2）使用编译器将源代码编译成目标文件
        cc -c xx.m
        a. 预处理
        b. 检查语法
        c. 编译
    3）链接
        cc xx.o  会报错
        如果程序中使用到了框架中的函数或者类，那么在链接的时候，就必须要告诉编译器
        去哪一个框架中找这个类或函数，所以，应该是这样的：
        cc xx.o -framework 框架名称
 
        例： cc test.o -framework Foundation
    4）链接成功，生成可执行文件 a.out
 
 
异常处理：
    1）目的：为了让程序在执行的时候如果发生了异常而不崩溃，继续往下执行
    2）语法
         @try
         {
            //将有可能发生异常的代码放在这
            //如果发生了异常，立即跳转到@catch代码段中执行
            //如果没有发生异常，就会略过@catch往下执行
         }
         @catch(NSException *ex)
         {
            //只有在@try出现异常代码才会执行
            //一般写下处理异常的代码
            //@cath的参数NSException *ex可以通过%@打印出ex指向的对象的值，就是异常的原因
         }
         @finally
         {
            //无论@try有没有出现异常，都会执行
 
         }
 
    3）注意：C语言的错误基本无法识别出来
 
 

 
 野指针
    C语言：定义一个指针变量没有初始化，这个指针变量指向随机的一块空间，这个指针就叫做野指针；
    OC中的野指针：指针指向的对象已经被回收了。这样的指针叫做野指针。
 
 僵尸对象
    一个已经被释放的对象，但是这个对象所占用的空间还没有分配给别人，这样的对象就叫做僵尸对象。
 
    僵尸对象的实时检查机制，打开这个机制，只要访问的是僵尸对象，无论空间是否被分配，都会报错。
 
 
 static 修饰符
    1. 在C语言中，可以修饰局部变量、全局变量和函数，
       从而把变量声明在内存的常量区，只有在程序结束的时候，变量才会被回收
 
    2. 在OC中，
        static不能修饰对象属性，也不能修饰方法，但可以修饰方法中的局部变量
 
OC最重要的一个机制：消息机制。

静态类型
    指的是一个指针指向的对象是一个本类对象。
 
动态类型
    指的是一个指针指向的对象不是本类对象。
 
 动态类型检测 - 反射
    a）判断对象中是否有这个方法可以执行 --最常用
        [p1 respondsToSelector:(SEL)@selector(方法名)];
 
      判断类中是否有指定类的方法
        [Student instancesRespondToSelector:@selector(方法名)];
 
    b）判断指定对象是否是为指定类的对象或者子对象
        [p1 isKindOfClass:[Person class]];
 
    c）判断对象中是否为指定类的对象，不包括子类
        [s1 isMemberOfClass:[Student class]];
 
    d）判断对象是否为指定类的子类
        [p1 isSubclassOfClass:[Student class]];
 
 集合的内存管理：
    MRC 将对象存入到集合中，会让对象的引用计数器+1
        但集合被销毁的时，里面的对象会发送一条release消息
 
    在ARC下，集合中的元素是一个强指针类型
 
 
 单例模式
    一个类对象，无论在何时何地创建，创建的都是同一个对象。
    特点：单例对象可以被共享，存储在单例对象的数据可以被共享。
    - 如果数据需要被整个程序共享，将数据以属性的方法存储在单例对象中。
 
    实现原理：因为创建对象，都要调用alloc方法，申请空间。而alloc方法本质上调用了allocWithZone:方法
            故，重写+ allocWithZone: 方法就能实现 代码如下
 
     + (instancetype)allocWithZone:(struct _NSZone *)zone
     {
         static id instance = nil;
         if(instance == nil)
         {
            instance = [super allocWithZone:zone];
         }
         return  instance;
     }
 
 单例模式的规范：
    如果类是一个单例模式，要求类提供一个类方法来返回这个单例对象。
    类方法名，必须以shared类名，default类名
 
 
 
 线程，最基本的执行单元
 
 多线程
     优点：
     1.能适当的提高程序的执行效率
     2.能适当提高内存和CPU的利用率
     3.线程上的任务完成之后，会自动的销毁
 
     缺点：
     1.开启线程需要占用一定的内存空间（默认情况下，每个线程占512KB）
     2.如果开启大量的线程，会占用大量的内存空间，降低程序的性能
     3.线程越多，CPU在调用线程上的开销就越大
     4.程序的设计更加复杂，比如线程间的通信、多线程的数据共享
 
 主线程
     一个程序运行后，默认会开启一个线程，称为主线程或者“UI线程”
     主线程一般用来用户交互，刷新UI界面、处理UI事件（比如：点击、滚动、拖拽等事件）
  使用注意：
     耗时操作不放在主线程，因为耗时操作会卡主线程，严重影响UI的流畅度，给用户一种卡的感觉。
 
    几乎所有UIKit提供的类都是线程不安全的，所有更新UI的操作都在主线程上。
    所有Mutable的类都是线程不安全的
 
 
 iOS中多线程的技术方案
    1.pthread -  跨平台、可移植
         a）一套通用的多线程API
         b）适用于Unix\Linux\Windows等系统
         c）C语言
         d）使用难度大，线程生命周期程序员来管理
         （几乎不用该方案）
 
    2.NSThread - Foundation框架提供的一个类- OC语言
        a）本质是对pthread的封装，线程生命周期也需要程序员来管理
        b）使用更加面向对象，简单易用，可以直接操作线程对象
        c）偶尔使用
 
    3.GCD
        a）旨在替代NSThread等线程技术，充分利用设备的多核
        b）使用C语言编写，本质是函数
        c）线程生命周期自动管理，经常使用
 
    4.NSOpretion - Foundation框架提供的一个类
        a）OC语言编写，使用更加面向对象
        b）底层基于GCD，比GCD多了一些更简单实用的功能
        c）线程生命周期自动管理，经常使用
        d）苹果推荐使用
 
 修饰符
 
 
 1. week - 只能在ARC下使用
    - 修饰的对象不会对引用计数器+1
    a）UI控件都使用week修饰
        不是因为循环引用，而是控件在被添加到视图上的时候，已经被控制器的subview属性强引用了，
        如果使用strong修饰，控制器本身也会对控件进行强引用，这样需要释放控件的时候，就需要释放两次。
       （使用strong也不会出错，也不会出现强引用）
 
    b） delegate使用week修饰
        为了避免循环引用。因为控制器（vc）-> 对类进行强引用 -> 类对delegate引用 -> delegeate也对控制器强引用
                                                        (类本身是strong)    (Xxx.delegate = self.)
 
   注意：  week和assign的区别
         - week只能在ARC下使用
         - assign在ARC和MRC都能使用
 
 2. copy - 在ARC和MRC下都能使用
    a）NSString 类型用copy修饰
        主要用于深拷贝和浅拷贝的区别，如果需要被赋值的对象的值不受本对象的值更改而更改，需要用copy进行深拷贝。
    b）block 类型用copy修饰
        因为block的本质是存储在栈区的，__NSStackBlock__，会被系统自动回收
        copy是将block包装为__NSMallocBlock__的类型，存储在堆区，这样不会被系统回收
 
 
 3. strong - 只能在ARC下使用
    - 其他OC对象都用strong来修饰 为引用计数器+1
 


 
 */


//是C语言#include 的增强版 -> 同一个文件，无论被#import多少遍，只会包含一次。
#import <Foundation/Foundation.h>
#import "SingleCase.h"

int main(int argc, const char * argv[])
{
   
    Person *p1 = [Person new];
    Person *p2 = [Person new];
    Person *p3 = [Person new];
    //三个地址指向同一个对象
    NSLog(@"\np1 = %p\np2 = %p\np3 = %p",p1,p2,p3);
    
    return 0;
}
